﻿using System;
using Microsoft.SPOT.Hardware;
using Gadgeteer;

namespace GHIElectronics.NETMF.Hardware
{
    internal partial class FezPanda : Board
    {
        static FezPanda()
        {
            Board.Hardware = new FezPanda();
        }

        /// <summary>Translates a socket pin to a Cpu.Pin</summary>
        /// <param name="socket">The Socket #</param>
        /// <param name="pin">The pin on the socket</param>
        /// <returns>The Cpu.Pin</returns>
        public override Cpu.Pin GetPin(int socket, int pin)
        {
            if (socket == 1)
            {
                if (pin == 3) return (Cpu.Pin)0x13; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di4
                if (pin == 4) return (Cpu.Pin)0x12; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di1
                if (pin == 5) return (Cpu.Pin)0x14; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di0
                if (pin == 6) return (Cpu.Pin)0x07; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di6
                if (pin == 7) return (Cpu.Pin)0x29; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di11
                if (pin == 8) return (Cpu.Pin)0x28; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di12
                if (pin == 9) return (Cpu.Pin)0x2a; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di13
            }
            else if (socket == 2)
            {
                if (pin == 3) return (Cpu.Pin)0x1c; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.An0
                if (pin == 4) return (Cpu.Pin)0x1a; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.An1
                if (pin == 5) return (Cpu.Pin)0x18; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.An2
                if (pin == 6) return (Cpu.Pin)0x16; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.An3
                // Pin 7 is not connected
                if (pin == 8) return (Cpu.Pin)0x1d; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.An4
                if (pin == 9) return (Cpu.Pin)0x20; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.An5
            }
            else if (socket == 3)
            {
                if (pin == 3) return (Cpu.Pin)0x0f; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di7
                if (pin == 4) return (Cpu.Pin)0x1f; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di3
                if (pin == 5) return (Cpu.Pin)0x21; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di2
                if (pin == 6) return (Cpu.Pin)0x17; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di8
                if (pin == 7) return (Cpu.Pin)0x02; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di5
                if (pin == 8) return (Cpu.Pin)0x19; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di9
                if (pin == 9) return (Cpu.Pin)0x23; // GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di10
            }
            return Cpu.Pin.GPIO_NONE;
        }

        /// <summary>Translates a socket pin to a AnalogIn.Pin</summary>
        /// <param name="socket">The Socket #</param>
        /// <param name="pin">The pin on the socket</param>
        /// <returns>The AnalogIn.Pin</returns>
        public static AnalogIn.Pin GetAnalog(int socket, int pin)
        {
            if (socket == 2)
            {
                if (pin == 3) return (AnalogIn.Pin)0x00; // GHIElectronics.NETMF.FEZ.FEZ_Pin.AnalogIn.An0
                if (pin == 4) return (AnalogIn.Pin)0x01; // GHIElectronics.NETMF.FEZ.FEZ_Pin.AnalogIn.An1
                if (pin == 5) return (AnalogIn.Pin)0x02; // GHIElectronics.NETMF.FEZ.FEZ_Pin.AnalogIn.An2
                if (pin == 6) return (AnalogIn.Pin)0x03; // GHIElectronics.NETMF.FEZ.FEZ_Pin.AnalogIn.An3
                // Pin 7 is not connected
                if (pin == 8) return (AnalogIn.Pin)0x04; // GHIElectronics.NETMF.FEZ.FEZ_Pin.AnalogIn.An4
                if (pin == 9) return (AnalogIn.Pin)0x05; // GHIElectronics.NETMF.FEZ.FEZ_Pin.AnalogIn.An5
            }
            throw new IndexOutOfRangeException();
        }

        /// <summary>Translates a socket pin to a PWM.Pin</summary>
        /// <param name="socket">The Socket #</param>
        /// <param name="pin">The pin on the socket</param>
        /// <returns>The PWM.Pin</returns>
        public static PWM.Pin GetPWM(int socket, int pin)
        {
            if (socket == 1)
            {
                if (pin == 6) return (PWM.Pin)0x06; // GHIElectronics.NETMF.FEZ.FEZ_Pin.PWM.Di6
            }
            else if (socket == 3)
            {
                if (pin == 6) return (PWM.Pin)0x03; // GHIElectronics.NETMF.FEZ.FEZ_Pin.PWM.Di8
                if (pin == 7) return (PWM.Pin)0x05; // GHIElectronics.NETMF.FEZ.FEZ_Pin.PWM.Di5
                if (pin == 8) return (PWM.Pin)0x02; // GHIElectronics.NETMF.FEZ.FEZ_Pin.PWM.Di9
                if (pin == 9) return (PWM.Pin)0x01; // GHIElectronics.NETMF.FEZ.FEZ_Pin.PWM.Di10
            }
            throw new IndexOutOfRangeException();
        }

        /// <summary>Translates a socket to a serial port on the Go! Mainboard</summary>
        /// <param name="socket">The Socket #</param>
        /// <returns>The serial port name</returns>
        public override string GetSerial(int socket)
        {
            if (socket == 1)
                return "COM1";
            else if (socket == 3)
                return "COM2";

            return "N/A";
        }

        /// <summary>Checks if the socket supports the given type</summary>
        /// <param name="socket">The Socket #</param>
        /// <param name="type">Socket type</param>
        /// <returns>true if it's supported</returns>
        public override bool GetSupported(int socket, char type)
        {
            if (socket == 1)
            {
                if (type == 'S') return true;
                if (type == 'U') return true;
                if (type == 'X') return true;
                if (type == 'Y') return true;
            }
            else if (socket == 2)
            {
                if (type == 'A') return true;
                if (type == 'I') return true;
                if (type == 'X') return true;
            }
            else if (socket == 3)
            {
                if (type == 'P') return true;
                if (type == 'U') return true;
                if (type == 'X') return true;
                if (type == 'Y') return true;
            }
            return false;
        }

        /// <summary>Creates a new analog input port</summary>
        /// <param name="socket">The socket on which the port exists</param>
        /// <param name="pin">The pin #</param>
        public override AnalogInProvider GetAnalogInProvider(int socket, int pin)
        {
            AnalogInProvider Ret = new AnalogInput();
            Ret.Init(socket, pin);
            return Ret;
        }

        /// <summary>Creates a new PWM output port</summary>
        /// <param name="socket">The socket on which the port exists</param>
        /// <param name="pin">The pin #</param>
        public override PWMOutProvider GetPWMOutProvider(int socket, int pin)
        {
            PWMOutProvider Ret = new PWMOut();
            Ret.Init(socket, pin);
            return Ret;
        }
    }
}
